package library.frame;

import com.sun.star.beans.XPropertySet;
import com.sun.star.container.XEnumeration;
import com.sun.star.container.XEnumerationAccess;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.text.XTextFieldsSupplier;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.util.XCloseable;
import com.sun.star.util.XRefreshable;
import library.logic.*;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.*;
import java.util.List;

/**
 * User: RockCrazy
 * Date: 21.01.12
 * Time: 10:23
 */
public class WinJournal extends JDialog implements ActionListener
{

	private static final int WIN_HEIGHT = 800;   // высота окна
	private final static int WIN_WIDTH = 300;   // ширина окна
	private final static int X = 10;      // левая граница метки для Label
	private final static int X2 = 130;     // левая граница метки для поля
	private final static int WIDTH = 170;     // ширина поля
	private final static int HEIGHT = 20;     // высота поля
	private JTable journalTab;
	private JSplitPane splitPane;

	private JTable paramPrint;

	// Владелец нашего окна - вводим для вызова нужного нам метода
	private MainFrame owner;
	private ManagementSystem ms = null;
	// Результат нажатия кнопок
	private boolean result = false;
	// Параметры задания
	private int journalId = 0;
	private JComboBox booksList;
	private JComboBox readersList;
    private JSpinner DateVidano = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
	private JSpinner DateVozvrat = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
    private JCheckBox chbSdano;
	
	public WinJournal(List<Reader> readers, List<Book> books, boolean newJournal, MainFrame mainFrame)
	{
		this.owner = owner;

		// Установить заголовок
		setTitle("Журнал выдачи книг");

		Container mainCont = getContentPane();
		mainCont.setLayout(new BorderLayout());

		/**** Cоздаем экземпляры компонент для левой панели ****/
		readersList = new JComboBox(new Vector<Reader>(readers));
		booksList = new JComboBox(new Vector<Book>(books));

		chbSdano = new JCheckBox("Сдано");
		chbSdano.setSelected(false);

		/*** Левая панель **/
		JPanel centrPanel = new JPanel();
		centrPanel.setLayout(null);

		/*** Читатели ****/
		JLabel lReaders = new JLabel("Читатель:", JLabel.LEFT);
		lReaders.setBounds(X, 10, WIDTH, HEIGHT);	// X и Y координаты самой левой верхней точки компонента, ширина и высота.
		readersList.setBounds(X2, 10, WIDTH, HEIGHT);
		centrPanel.add(lReaders);
		centrPanel.add(readersList);

		/*** Книги ***/
		JLabel lBooks = new JLabel("Книга:", JLabel.LEFT);
		lBooks.setBounds(X, 35, WIDTH, HEIGHT);
		centrPanel.add(lBooks);
		booksList.setBounds(X2, 35, WIDTH, HEIGHT);
		centrPanel.add(booksList);

		/*** Дата выдачи ***/
		JLabel lDateVidano = new JLabel("Дата приёма:", JLabel.LEFT);
		lDateVidano.setBounds(X, 60, WIDTH, HEIGHT);
		DateVidano.setBounds(X2, 60, WIDTH, HEIGHT);
		centrPanel.add(lDateVidano);
		centrPanel.add(DateVidano);

		/*** Дата возврата ***/
		JLabel lDateVozvrat = new JLabel("Дата выдачи:", JLabel.LEFT);
		lDateVozvrat.setBounds(X, 85, WIDTH, HEIGHT);
		DateVozvrat.setBounds(X2, 85, WIDTH, HEIGHT);
		centrPanel.add(lDateVozvrat);
		centrPanel.add(DateVozvrat);

		/*** Готовность ***/
		chbSdano.setBounds(X, 110, WIDTH - 70, HEIGHT);
		centrPanel.add(chbSdano);

		/*** Нижняя панель **/
		JPanel botPanel = new JPanel();
		FlowLayout botPanelLayout = new FlowLayout();
		botPanel.setLayout(botPanelLayout);
		botPanelLayout.setAlignment(FlowLayout.RIGHT);
		botPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

		JButton btnCancel = new JButton("Выход");
		btnCancel.setName("Выход");
		btnCancel.addActionListener(this);
		botPanel.add(btnCancel);

		// При добавлении задания
		if (newJournal)
		{
			JButton btnOk = new JButton("ОК");
			btnOk.setName("ОК");
			btnOk.addActionListener(this);
			botPanel.add(btnOk);

			JButton btnNew = new JButton("Добавить");
			btnNew.setName("Добавить");
			btnNew.addActionListener(this);
			botPanel.add(btnNew);
		}
		// При редактировании
		else
		{
			JOptionPane.showMessageDialog(this, "<html><font color=red>Внимание! Включен режим редактирования!");
			setTitle("Редактирование заданий");

			JButton btnDel = new JButton("<html><font color=red>Удалить");
			btnDel.setName("Delete");
			btnDel.addActionListener(this);
			botPanel.add(btnDel);

			JButton btnSave = new JButton("Сохранить");
			btnSave.setName("Сохранить");
			btnSave.addActionListener(this);
			botPanel.add(btnSave);
		}

		JButton btnPrint = new JButton("Печать");
		btnPrint.setName("Печать");
		btnPrint.addActionListener(this);
		botPanel.add(btnPrint);


		/*** Правая панель с таблицей ***/
		// Создаем таблицу для вывода списка клиентов
		journalTab = new JTable(1, 5);
		journalTab.getSelectionModel().addListSelectionListener(new RowListener());
		reloadJournal();
		JScrollPane scrollPane = new JScrollPane(journalTab);

		// создаем splitPanel
		splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centrPanel, scrollPane);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(320);


		// Добавляем панели в контейнер
		mainCont.add(new JPanel(), BorderLayout.NORTH);
		mainCont.add(new JPanel(), BorderLayout.LINE_START);
		mainCont.add(new JPanel(), BorderLayout.LINE_END);
		mainCont.add(splitPane, BorderLayout.CENTER);
		mainCont.add(botPanel, BorderLayout.SOUTH);


		// Устанавливаем поведение формы при закрытии - не закрывать совсем.
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

		// Получаем размеры экрана
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		setBounds(((int) d.getWidth() - library.frame.WinJournal.WIN_WIDTH) / 2, ((int) d.getHeight() - library.frame.WinJournal.WIN_HEIGHT) / 2, 700, 640);
	}

	// Установить поля соответственно переданным данным о читателе
	public void setJournal(Journal journal)
	{
		// подбираем по номеру читателя ReadersID
		journalId = journal.getJournalId();
		for (int i = 0; i < readersList.getModel().getSize(); i++)
		{
			Reader reader = (Reader) readersList.getModel().getElementAt(i);
			if (reader.getReaderId() == journal.getReaderId())
			{
				readersList.setSelectedIndex(i);
				break;
			}
		}
		// подбираем список по booksID
		for (int i = 0; i < booksList.getModel().getSize(); i++)
		{
			Book books = (Book) booksList.getModel().getElementAt(i);
			if (books.getBookId() == journal.getBookId())
			{
				booksList.setSelectedIndex(i);
				break;
			}
		}
		
		DateVidano.getModel().setValue(journal.getDateVidano());
		DateVozvrat.getModel().setValue(journal.getDateVozvrat());
		chbSdano.setSelected(journal.isSdano());
	}


	// Вернуть данные в виде нового задания с соотвтествующими полями
	public Journal getJournal()
	{
		Journal journal = new Journal();
		journal.setJournalId(journalId);
		journal.setReaderId(((Reader) readersList.getSelectedItem()).getReaderId());
		journal.setBookId(((Book) booksList.getSelectedItem()).getBookId());
		Date datePr = ((SpinnerDateModel) DateVidano.getModel()).getDate();
		journal.setDateVidano(datePr);
		Date dateVz = ((SpinnerDateModel) DateVozvrat.getModel()).getDate();
		journal.setDateVozvrat(dateVz);
		journal.setSdano(chbSdano.isSelected());
		return journal;
	}

	// Получить результат, true - кнопка ОК, false - кнопка Cancel
	public boolean getResult()
	{
		return result;
	}


	public void actionPerformed(ActionEvent e)
	{
		JButton src = (JButton) e.getSource();
		if (src.getName().equals("Добавить"))
		{
			result = true;
			try
			{
				ManagementSystem.getInstance().insertJournal(getJournal());
				reloadJournal();
				DateVidano = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
				DateVozvrat = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
				chbSdano.setSelected(false);
			}
			catch (Exception sql_e)
			{
				//JOptionPane.showMessageDialog(this, sql_e.getMessage());
				JOptionPane.showMessageDialog(this, "<html><font color=red>Не все поля заполнены!");
			}
			return;
		}
		if (src.getName().equals("Сохранить"))
		{
			result = true;
			try
			{
				ManagementSystem.getInstance().updateJournal(getJournal());
				reloadJournal();

			}
			catch (Exception sql_e)
			{
				JOptionPane.showMessageDialog(this, sql_e.getMessage());
			}
			return;
		}
		if (src.getName().equals("Удалить"))
		{

			result = true;
			deleteJournal();
			DateVidano = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
			DateVozvrat = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
			chbSdano.setSelected(false);
			return;

		}

		if (src.getName().equals("OK"))
		{
			result = true;
		}
		if (src.getName().equals("Печать"))
		{
			OOOReportGenerator printGen = new OOOReportGenerator();
			DynamicTableModel dmtParam = new DynamicTableModel(false);
			JTable paramPrint = new JTable(dmtParam);
			if (journalId != 0)
			{
				try
				{
					ManagementSystem ms = new ManagementSystem();
					dmtParam.setDataSource(ms.stringSQL("SELECT j.id_journal, r.fam, r.name, r.otch, r.adress, r.phone,  " +
							"b.id_book, b.book_name, b.author, j.date_vidano, j.date_vozvrat " +
							"FROM journal AS j, reader AS r, book AS b " +
							"WHERE j.id_reader = r.id_reader AND j.id_book = b.id_book " +
							"AND j.id_journal = " + journalId));

				}
				catch (Exception e1)
				{
					e1.printStackTrace();
				}

			}
			else
			{
				JOptionPane.showMessageDialog(WinJournal.this, "Выберите необходимую запись в журнале!");
				return;
			}

			HashMap<String, Object> variableMap = new HashMap<String, Object>();

			variableMap.put("JOURNAL_ID", dmtParam.getValueAt(0, 0));
			variableMap.put("READER_FAM", dmtParam.getValueAt(0, 1));
			variableMap.put("READER_NAME", dmtParam.getValueAt(0, 2));
			variableMap.put("READER_OTCH", dmtParam.getValueAt(0, 3));
			variableMap.put("READER_ADRESS", dmtParam.getValueAt(0, 4));
			variableMap.put("READER_PHONE", dmtParam.getValueAt(0, 5));
			variableMap.put("BOOK_ID", dmtParam.getValueAt(0, 6));
			variableMap.put("BOOK_NAME", dmtParam.getValueAt(0, 7));
			variableMap.put("AUTHOR", dmtParam.getValueAt(0, 8));
			variableMap.put("DATE_VIDANO", dmtParam.getValueAt(0, 9));
			variableMap.put("DATE_VOZVRAT", dmtParam.getValueAt(0, 10));
			try
			{
				printGen.connect(Config.URL_OPEN_OFFICE);

				XComponent currentDocument = printGen.openDocument(Config.URL_FILE_TEMPLATE);
				XTextFieldsSupplier xTextFieldsSupplier = (XTextFieldsSupplier) UnoRuntime.queryInterface(XTextFieldsSupplier.class, currentDocument);
				// Создадим перечисление всех полей документа
				XEnumerationAccess xEnumerationAccess = xTextFieldsSupplier.getTextFields();
				XEnumeration xTextFieldsEnumeration = xEnumerationAccess.createEnumeration();
				XRefreshable xRefreshable = (XRefreshable) UnoRuntime.queryInterface(XRefreshable.class, xEnumerationAccess);

				while (xTextFieldsEnumeration.hasMoreElements())
				{
					Object service = xTextFieldsEnumeration.nextElement();
					XServiceInfo xServiceInfo = (XServiceInfo) UnoRuntime.queryInterface(XServiceInfo.class, service);

					if (xServiceInfo.supportsService("com.sun.star.text.TextField.SetExpression"))
					{
						XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, service);
						String name = (String) xPropertySet.getPropertyValue("VariableName");
						Object content = variableMap.get(name);
						//xPropertySet.setPropertyValue("SubType",new Short(com.sun.star.text.SetVariableType.STRING));
						xPropertySet.setPropertyValue("Content", content == null ? " " : content.toString());
						//xPropertySet.setPropertyValue("IsVisible", true);
					}
				}
				xRefreshable.refresh();

				String[] cmds = {"Print"};
				printGen.executeCommands(cmds);
				/* можно еще
				* printDocument(currentDocument) - распечатать на принтере по умолчанию
				* saveDocument (currentDocument, props) - сохранить текущий документ
				* saveAsDocument (currentDocument, sURL, props) - сохранить под новым именем
				*/
				printGen.closeDocument(currentDocument, false);
				XCloseable c = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, currentDocument);
				while (true)
				{
					try
					{
						c.close(false);
						break;
					}
					catch (com.sun.star.util.CloseVetoException eC)
					{
					}
					Thread.sleep(200);
				}
			}
			catch (Exception ex)
			{
				System.out.println("<html><font color=red>Ошибка печати! Проверьте пути в main.properties! ");
			}
		}
		if (src.getName().equals("Выход"))
		{
			result = false;
		}


		setVisible(false);
	}

	private void deleteJournal()
	{
		try
		{
			ms = new ManagementSystem();
			Thread t = new Thread()
			{
				public void run()
				{
					if (journalTab != null)
					{
						JournalTableModel stm = (JournalTableModel) journalTab.getModel();
						// Проверяем - выделен ли хоть какой-нибудь исполнитель
						if (journalTab.getSelectedRow() >= 0)
						{
							if (JOptionPane.showConfirmDialog(WinJournal.this, "<html><font color=red>Вы хотите удалить задание?", "Удаление задания", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
							{
								// Вот где нам пригодился метод getExecutant(int rowIndex)
								Journal journal = stm.getJournal(journalTab.getSelectedRow());
								try
								{
									ms.deleteJournal(journal);
									reloadJournal();
								}
								catch (SQLException e)
								{
									JOptionPane.showMessageDialog(WinJournal.this, e.getMessage());
								}
							}
						} // Если исполнитель не выделен - сообщаем пользователю, что это необходимо
						else
						{
							JOptionPane.showMessageDialog(WinJournal.this, "Необходимо выделить задание в списке");
						}

					}
				}
			};
			t.start();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	// метод для обновления списка заданий
	public void reloadJournal()
	{
		readersList.setSelectedIndex(-1);
		booksList.setSelectedIndex(-1);

		// Создаем анонимный класс для потока
		Thread t = new Thread()
		{
			// Переопределяем в нем метод run
			public void run()
			{
				if (journalTab != null)
					try
					{
						// Получаем список заданий
						ms = new ManagementSystem();
						Collection<Journal> journalb = ms.getJournals();
						// И устанавливаем модель для таблицы с новыми данными
						journalTab.setModel(new JournalTableModel(new Vector<Journal>(journalb)));
					}
					catch (SQLException e)
					{
						JOptionPane.showMessageDialog(WinJournal.this, e.getMessage());
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
			}// Окончание нашего метода run
		};// Окончание определения анонимного класса
		// И теперь мы запускаем наш поток
		t.start();
	}

	// Метод для обеспечения интерфейса ListSelectionListener
	public void valueChanged(ListSelectionEvent e)
	{
		if (!e.getValueIsAdjusting())
		{
			reloadJournal();
		}

	}


	private class RowListener implements ListSelectionListener
	{
		public void valueChanged(ListSelectionEvent event)
		{
			JournalTableModel jtm = (JournalTableModel) journalTab.getModel();
			Journal j = jtm.getJournal(journalTab.getSelectedRow());

			if (event.getValueIsAdjusting())
			{
				return;
			}
			try
			{
				setJournal(j);
			}
			catch (Exception sql_e)
			{
				JOptionPane.showMessageDialog(WinJournal.this, "Данные успешно сохранены");
			}
		}
	}

}

